using System;
using System.Collections.Generic;
using System.Text;
using System.Globalization;
using System.ComponentModel;
using System.Reflection;
using FRW.Common.Extensions;

namespace Money
{
    public class Transaction
    {
        public enum TransactionType
        {
            Cheque,

            [EnumDescriptionAttribute("Direct Debit")]
            DirectDebit,

            Charge,

            [EnumDescriptionAttribute("Standing Order")]
            StandingOrder,
            Transfer,
            Interest,
            Payment,
            Debit,

            [EnumDescriptionAttribute("Cash Withdrawal")]
            CashWithdrawal,
            Unknown,
            Ignore,
            Credit,
            Income,
            Expense,
            Refund
        };

        #region Fields
        // TODO convert this to an int or something similar
        private long _transactionNo;
        private long _destainationTransactionNo;
        private decimal _amount;
        private string _account;
        private string _description;
        private string _destinationAccount;
        private string _comment;
        private DateTime _date;
        private TransactionType _type;
        private long _importId;
        private string _importHandler;
        private int _categoryId;

        private bool _dirty = false;

        private static Categories _categories;

        private static Accounts _accounts;

        #endregion

        #region Properties

        public int CategoryId
        {
            get { return _categoryId; }
            set 
            {
                if (value != _categoryId)
                {
                    _categoryId = value;
                    DirtyTransaction();
                }
            }
        }

        public bool IsDirty { get { return _dirty; } }

        public Int64 TransactionNo 
        {
            get { return _transactionNo; }
            set 
            {
                if (value != _transactionNo)
                {
                    _transactionNo = value;
                    DirtyTransaction();
                }
            }
        }

        public string ImportHandler
        {
            get
            {
                if(string.IsNullOrWhiteSpace(_importHandler))
                {
                    switch(_account)
                    {
                        case "RBS":
                            _importHandler = "rbs-csv";
                            break;

                        case "Tesco":
                            _importHandler = "tesco-tsv";
                            break;
                    }
                }
                return _importHandler;
            }
            set
            {
                _importHandler = value;
            }
        }

        public decimal Amount
        {
            get { return _amount; }
            set 
            {
                if (value != _amount)
                {
                    _amount = value;
                    DirtyTransaction();
                }
            }
        }

        public string Account
        {
            get { return _account; }
            set 
            {
                if (!value.Equals(_account))
                {
                    _account = value;
                    DirtyTransaction();
                }
            }
        }

        public string DestinationAccount
        {
            get { return _destinationAccount; }
            set 
            {
                if (string.IsNullOrWhiteSpace(value) && string.IsNullOrWhiteSpace(_destinationAccount))
                {
                }
                else
                {
                    if (!value.Equals(_destinationAccount))
                    {
                        _destinationAccount = value;
                        DirtyTransaction();
                    }
                }
            }
        }

        public long DestinationTransactionNo
        {
            get { return _destainationTransactionNo; }
            set
            {
                if (value != _destainationTransactionNo)
                {
                    _destainationTransactionNo = value;
                    DirtyTransaction();
                }
            }
        }

        public DateTime Date
        {
            get { return _date; }
            set 
            {
                if (value != _date)
                {
                    _date = value;
                    DirtyTransaction();
                }
            }
        }

        public Transaction.TransactionType Type
        {
            get { return _type; }
            set 
            {
                if (value != _type)
                {
                    _type = value;
                    DirtyTransaction();
                }
            }
        }

        public string TypeText
        {
            get
            {
                return _type.ToString();
            }
        }

        public string Description
        {
            get { return _description; }
            set
            {
                if (string.IsNullOrWhiteSpace(value) && string.IsNullOrWhiteSpace(_description))
                {
                }
                else
                {
                    if (!value.Equals(_description))
                    {
                        _description = value;
                        DirtyTransaction();
                    }
                }
            }
        }

        public string Comment
        {
            get { return _comment; }
            set
            {
                if (string.IsNullOrWhiteSpace(value) && string.IsNullOrWhiteSpace(_comment))
                {
                }
                else
                {
                    if (!value.Equals(_comment))
                    {
                        _comment = value;
                        DirtyTransaction();
                    }
                }
            }
        }

        public string Category
        {
            get 
            {
                if (_categories != null)
                {
                    return _categories.GetCategoryName(CategoryId);
                }

                throw new InvalidOperationException();
            }
        }

        public string CatgeoryFullName
        {
            get
            {
                if (_categories != null)
                {
                    return _categories.GetFullCategoryName(_categoryId);
                }

                throw new InvalidOperationException();
            }
        }

        public long ImportId
        {
            get { return _importId; }
            set
            {
                if (value != _importId)
                {
                    _importId = value;
                    DirtyTransaction();
                }
            }
        }

        public string CategoryGroup 
        {
            get
            {
                if (_categories != null)
                {
                    return _categories.GetParentName(CategoryId);
                }

                throw new InvalidOperationException();
            }
        }

        /// <summary>
        /// Get the parent category Id for this transaction
        /// </summary>
        public int ParentId
        {
            get
            {
                if (_categories != null)
                {
                    return _categories.GetParentId(CategoryId);
                }

                throw new InvalidOperationException();
            }
        }

        #endregion

        #region Constructors
 
        public Transaction()
        {
            _date = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
        }

        public Transaction(decimal amount, DateTime transDate, string transDesc)
            : this(amount, transDate, transDesc, Transaction.TransactionType.Debit)
        {
        }

        public Transaction(decimal amount, DateTime transDate, string transDesc, Transaction.TransactionType transType)
        {
            Amount = amount;
            Date = transDate;
            Type = transType;
            Description = transDesc;
        }
        #endregion


        public static void SetAccounts(Accounts accounts)
        {
            _accounts = accounts;
        }

        public static void SetCategories(Categories categories)
        {
            _categories = categories;
        }

        public void Saved()
        {
            _dirty = false;
        }

        public bool Compare(Transaction transaction)
        {
            bool equals = false;

            if (TransactionNo == transaction.TransactionNo)
            {
                equals = true;
            }

            return equals;
        }

        public Transaction Copy()
        {
            Transaction transaction = (Transaction)this.MemberwiseClone();

            return transaction;
        }

        private void DirtyTransaction()
        {
            _dirty = true;
        }

        /// <summary>
        /// Copy all details from one transaction into this one
        /// </summary>
        /// <param name="transaction"></param>
        public void CopyFrom(Transaction transaction)
        {
            _account = transaction.Account;
            _amount = transaction.Amount;
            _description = transaction.Description;
            _comment = transaction.Comment;
            _date = transaction.Date;
            _importId = transaction.ImportId;
            _transactionNo = transaction.TransactionNo;
            _type = transaction.Type;
            _categoryId = transaction.CategoryId;
            _destinationAccount = transaction.DestinationAccount;
            _dirty = transaction.IsDirty;
        }
    }
}
